1   /*
2    * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.java.util.jar.pack;
27  
28  import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
29  import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
30  import com.sun.java.util.jar.pack.ConstantPool.Entry;
31  import com.sun.java.util.jar.pack.ConstantPool.Index;
32  import com.sun.java.util.jar.pack.ConstantPool.IndexGroup;
33  import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
34  import com.sun.java.util.jar.pack.ConstantPool.NumberEntry;
35  import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
36  import com.sun.java.util.jar.pack.ConstantPool.StringEntry;
37  import com.sun.java.util.jar.pack.Package.Class;
38  import com.sun.java.util.jar.pack.Package.File;
39  import com.sun.java.util.jar.pack.Package.InnerClass;
40  import java.io.IOException;
41  import java.io.OutputStream;
42  import java.io.PrintStream;
43  import java.util.ArrayList;
44  import java.util.Arrays;
45  import java.util.Comparator;
46  import java.util.HashMap;
47  import java.util.HashSet;
48  import java.util.List;
49  import java.util.Map;
50  import java.util.Set;
51  import static com.sun.java.util.jar.pack.Constants.*;
52  
53  /**
54   * Writer for a package file.
55   * @author John Rose
56   */
57  class PackageWriter extends BandStructure {
58      Package pkg;
59      OutputStream finalOut;
60  
61      PackageWriter(Package pkg, OutputStream out) throws IOException {
62          this.pkg = pkg;
63          this.finalOut = out;
64          // Caller has specified archive version in the package:
65          initPackageMajver(pkg.package_majver);
66      }
67  
68      void write() throws IOException {
69          boolean ok = false;
70          try {
71              if (verbose > 0) {
72                  Utils.log.info("Setting up constant pool...");
73              }
74              setup();
75  
76              if (verbose > 0) {
77                  Utils.log.info("Packing...");
78              }
79  
80              // writeFileHeader() is done last, since it has ultimate counts
81              // writeBandHeaders() is called after all other bands are done
82              writeConstantPool();
83              writeFiles();
84              writeAttrDefs();
85              writeInnerClasses();
86              writeClassesAndByteCodes();
87              writeAttrCounts();
88  
89              if (verbose > 1)  printCodeHist();
90  
91              // choose codings (fill band_headers if needed)
92              if (verbose > 0) {
93                  Utils.log.info("Coding...");
94              }
95              all_bands.chooseBandCodings();
96  
97              // now we can write the headers:
98              writeFileHeader();
99  
100             writeAllBandsTo(finalOut);
101 
102             ok = true;
103         } catch (Exception ee) {
104             Utils.log.warning("Error on output: "+ee, ee);
105             //if (verbose > 0)  ee.printStackTrace();
106             // Write partial output only if we are verbose.
107             if (verbose > 0)  finalOut.close();
108             if (ee instanceof IOException)  throw (IOException)ee;
109             if (ee instanceof RuntimeException)  throw (RuntimeException)ee;
110             throw new Error("error packing", ee);
111         }
112     }
113 
114     Set<Entry>                       requiredEntries;  // for the CP
115     Map<Attribute.Layout, int[]>     backCountTable;   // for layout callables
116     int[][]     attrCounts;       // count attr. occurences
117 
118     void setup() {
119         requiredEntries = new HashSet<>();
120         setArchiveOptions();
121         trimClassAttributes();
122         collectAttributeLayouts();
123         pkg.buildGlobalConstantPool(requiredEntries);
124         setBandIndexes();
125         makeNewAttributeBands();
126         collectInnerClasses();
127     }
128 
129     void setArchiveOptions() {
130         // Decide on some archive options early.
131         // Does not decide on: AO_HAVE_SPECIAL_FORMATS,
132         // AO_HAVE_CP_NUMBERS, AO_HAVE_FILE_HEADERS.
133         // Also, AO_HAVE_FILE_OPTIONS may be forced on later.
134         int minModtime = pkg.default_modtime;
135         int maxModtime = pkg.default_modtime;
136         int minOptions = -1;
137         int maxOptions = 0;
138 
139         // Import defaults from package (deflate hint, etc.).
140         archiveOptions |= pkg.default_options;
141 
142         for (File file : pkg.files) {
143             int modtime = file.modtime;
144             int options = file.options;
145 
146             if (minModtime == NO_MODTIME) {
147                 minModtime = maxModtime = modtime;
148             } else {
149                 if (minModtime > modtime)  minModtime = modtime;
150                 if (maxModtime < modtime)  maxModtime = modtime;
151             }
152             minOptions &= options;
153             maxOptions |= options;
154         }
155         if (pkg.default_modtime == NO_MODTIME) {
156             // Make everything else be a positive offset from here.
157             pkg.default_modtime = minModtime;
158         }
159         if (minModtime != NO_MODTIME && minModtime != maxModtime) {
160             // Put them into a band.
161             archiveOptions |= AO_HAVE_FILE_MODTIME;
162         }
163         // If the archive deflation is set do not bother with each file.
164         if (!testBit(archiveOptions,AO_DEFLATE_HINT) && minOptions != -1) {
165             if (testBit(minOptions, FO_DEFLATE_HINT)) {
166                 // Every file has the deflate_hint set.
167                 // Set it for the whole archive, and omit options.
168                 archiveOptions |= AO_DEFLATE_HINT;
169                 minOptions -= FO_DEFLATE_HINT;
170                 maxOptions -= FO_DEFLATE_HINT;
171             }
172             pkg.default_options |= minOptions;
173             if (minOptions != maxOptions
174                 || minOptions != pkg.default_options) {
175                 archiveOptions |= AO_HAVE_FILE_OPTIONS;
176             }
177         }
178         // Decide on default version number (majority rule).
179         Map<Integer, int[]> verCounts = new HashMap<>();
180         int bestCount = 0;
181         int bestVersion = -1;
182         for (Class cls : pkg.classes) {
183             int version = cls.getVersion();
184             int[] var = verCounts.get(version);
185             if (var == null) {
186                 var = new int[1];
187                 verCounts.put(version, var);
188             }
189             int count = (var[0] += 1);
190             //System.out.println("version="+version+" count="+count);
191             if (bestCount < count) {
192                 bestCount = count;
193                 bestVersion = version;
194             }
195         }
196         verCounts.clear();
197         if (bestVersion == -1)  bestVersion = 0;  // degenerate case
198         int bestMajver = (char)(bestVersion >>> 16);
199         int bestMinver = (char)(bestVersion);
200         pkg.default_class_majver = (short) bestMajver;
201         pkg.default_class_minver = (short) bestMinver;
202         String bestVerStr = Package.versionStringOf(bestMajver, bestMinver);
203         if (verbose > 0)
204            Utils.log.info("Consensus version number in segment is "+bestVerStr);
205         if (verbose > 0)
206             Utils.log.info("Highest version number in segment is "+
207                            Package.versionStringOf(pkg.getHighestClassVersion()));
208 
209         // Now add explicit pseudo-attrs. to classes with odd versions.
210         for (Class cls : pkg.classes) {
211             if (cls.getVersion() != bestVersion) {
212                 Attribute a = makeClassFileVersionAttr(cls.minver, cls.majver);
213                 if (verbose > 1) {
214                     String clsVer = cls.getVersionString();
215                     String pkgVer = bestVerStr;
216                     Utils.log.fine("Version "+clsVer+" of "+cls
217                                      +" doesn't match package version "
218                                      +pkgVer);
219                 }
220                 // Note:  Does not add in "natural" order.  (Who cares?)
221                 cls.addAttribute(a);
222             }
223         }
224 
225         // Decide if we are transmitting a huge resource file:
226         for (File file : pkg.files) {
227             long len = file.getFileLength();
228             if (len != (int)len) {
229                 archiveOptions |= AO_HAVE_FILE_SIZE_HI;
230                 if (verbose > 0)
231                    Utils.log.info("Note: Huge resource file "+file.getFileName()+" forces 64-bit sizing");
232                 break;
233             }
234         }
235 
236         // Decide if code attributes typically have sub-attributes.
237         // In that case, to preserve compact 1-byte code headers,
238         // we must declare unconditional presence of code flags.
239         int cost0 = 0;
240         int cost1 = 0;
241         for (Class cls : pkg.classes) {
242             for (Class.Method m : cls.getMethods()) {
243                 if (m.code != null) {
244                     if (m.code.attributeSize() == 0) {
245                         // cost of a useless unconditional flags byte
246                         cost1 += 1;
247                     } else if (shortCodeHeader(m.code) != LONG_CODE_HEADER) {
248                         // cost of inflating a short header
249                         cost0 += 3;
250                     }
251                 }
252             }
253         }
254         if (cost0 > cost1) {
255             archiveOptions |= AO_HAVE_ALL_CODE_FLAGS;
256         }
257         if (verbose > 0)
258             Utils.log.info("archiveOptions = "
259                              +"0b"+Integer.toBinaryString(archiveOptions));
260     }
261 
262     void writeFileHeader() throws IOException {
263         pkg.checkVersion();
264         writeArchiveMagic();
265         writeArchiveHeader();
266     }
267 
268     // Local routine used to format fixed-format scalars
269     // in the file_header:
270     private void putMagicInt32(int val) throws IOException {
271         int res = val;
272         for (int i = 0; i < 4; i++) {
273             archive_magic.putByte(0xFF & (res >>> 24));
274             res <<= 8;
275         }
276     }
277 
278     void writeArchiveMagic() throws IOException {
279         putMagicInt32(pkg.magic);
280     }
281 
282     void writeArchiveHeader() throws IOException {
283         // for debug only:  number of words optimized away
284         int headerDiscountForDebug = 0;
285 
286         // AO_HAVE_SPECIAL_FORMATS is set if non-default
287         // coding techniques are used, or if there are
288         // compressor-defined attributes transmitted.
289         boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
290         if (!haveSpecial) {
291             haveSpecial |= (band_headers.length() != 0);
292             haveSpecial |= (attrDefsWritten.length != 0);
293             if (haveSpecial)
294                 archiveOptions |= AO_HAVE_SPECIAL_FORMATS;
295         }
296         if (!haveSpecial)
297             headerDiscountForDebug += AH_SPECIAL_FORMAT_LEN;
298 
299         // AO_HAVE_FILE_HEADERS is set if there is any
300         // file or segment envelope information present.
301         boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
302         if (!haveFiles) {
303             haveFiles |= (archiveNextCount > 0);
304             haveFiles |= (pkg.default_modtime != NO_MODTIME);
305             if (haveFiles)
306                 archiveOptions |= AO_HAVE_FILE_HEADERS;
307         }
308         if (!haveFiles)
309             headerDiscountForDebug += AH_FILE_HEADER_LEN;
310 
311         // AO_HAVE_CP_NUMBERS is set if there are any numbers
312         // in the global constant pool.  (Numbers are in 15% of classes.)
313         boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
314         if (!haveNumbers) {
315             haveNumbers |= pkg.cp.haveNumbers();
316             if (haveNumbers)
317                 archiveOptions |= AO_HAVE_CP_NUMBERS;
318         }
319         if (!haveNumbers)
320             headerDiscountForDebug += AH_CP_NUMBER_LEN;
321 
322         assert(pkg.package_majver > 0);  // caller must specify!
323         archive_header_0.putInt(pkg.package_minver);
324         archive_header_0.putInt(pkg.package_majver);
325         if (verbose > 0)
326             Utils.log.info("Package Version for this segment:"+
327                            Package.versionStringOf(pkg.getPackageVersion()));
328         archive_header_0.putInt(archiveOptions); // controls header format
329         assert(archive_header_0.length() == AH_LENGTH_0);
330 
331         final int DUMMY = 0;
332         if (haveFiles) {
333             assert(archive_header_S.length() == AH_ARCHIVE_SIZE_HI);
334             archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 32)
335             assert(archive_header_S.length() == AH_ARCHIVE_SIZE_LO);
336             archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 0)
337             assert(archive_header_S.length() == AH_LENGTH_S);
338         }
339 
340         // Done with unsized part of header....
341 
342         if (haveFiles) {
343             archive_header_1.putInt(archiveNextCount);  // usually zero
344             archive_header_1.putInt(pkg.default_modtime);
345             archive_header_1.putInt(pkg.files.size());
346         } else {
347             assert(pkg.files.isEmpty());
348         }
349 
350         if (haveSpecial) {
351             archive_header_1.putInt(band_headers.length());
352             archive_header_1.putInt(attrDefsWritten.length);
353         } else {
354             assert(band_headers.length() == 0);
355             assert(attrDefsWritten.length == 0);
356         }
357 
358         writeConstantPoolCounts(haveNumbers);
359 
360         archive_header_1.putInt(pkg.getAllInnerClasses().size());
361         archive_header_1.putInt(pkg.default_class_minver);
362         archive_header_1.putInt(pkg.default_class_majver);
363         archive_header_1.putInt(pkg.classes.size());
364 
365         // Sanity:  Make sure we came out to 26 (less optional fields):
366         assert(archive_header_0.length() +
367                archive_header_S.length() +
368                archive_header_1.length()
369                == AH_LENGTH - headerDiscountForDebug);
370 
371         // Figure out all the sizes now, first cut:
372         archiveSize0 = 0;
373         archiveSize1 = all_bands.outputSize();
374         // Second cut:
375         archiveSize0 += archive_magic.outputSize();
376         archiveSize0 += archive_header_0.outputSize();
377         archiveSize0 += archive_header_S.outputSize();
378         // Make the adjustments:
379         archiveSize1 -= archiveSize0;
380 
381         // Patch the header:
382         if (haveFiles) {
383             int archiveSizeHi = (int)(archiveSize1 >>> 32);
384             int archiveSizeLo = (int)(archiveSize1 >>> 0);
385             archive_header_S.patchValue(AH_ARCHIVE_SIZE_HI, archiveSizeHi);
386             archive_header_S.patchValue(AH_ARCHIVE_SIZE_LO, archiveSizeLo);
387             int zeroLen = UNSIGNED5.getLength(DUMMY);
388             archiveSize0 += UNSIGNED5.getLength(archiveSizeHi) - zeroLen;
389             archiveSize0 += UNSIGNED5.getLength(archiveSizeLo) - zeroLen;
390         }
391         if (verbose > 1)
392             Utils.log.fine("archive sizes: "+
393                              archiveSize0+"+"+archiveSize1);
394         assert(all_bands.outputSize() == archiveSize0+archiveSize1);
395     }
396 
397     void writeConstantPoolCounts(boolean haveNumbers) throws IOException {
398         for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
399             byte tag = ConstantPool.TAGS_IN_ORDER[k];
400             int count = pkg.cp.getIndexByTag(tag).size();
401             switch (tag) {
402             case CONSTANT_Utf8:
403                 // The null string is always first.
404                 if (count > 0)
405                     assert(pkg.cp.getIndexByTag(tag).get(0)
406                            == ConstantPool.getUtf8Entry(""));
407                 break;
408 
409             case CONSTANT_Integer:
410             case CONSTANT_Float:
411             case CONSTANT_Long:
412             case CONSTANT_Double:
413                 // Omit counts for numbers if possible.
414                 if (!haveNumbers) {
415                     assert(count == 0);
416                     continue;
417                 }
418                 break;
419             }
420             archive_header_1.putInt(count);
421         }
422     }
423 
424     protected Index getCPIndex(byte tag) {
425         return pkg.cp.getIndexByTag(tag);
426     }
427 
428 // (The following observations are out of date; they apply only to
429 // "banding" the constant pool itself.  Later revisions of this algorithm
430 // applied the banding technique to every part of the package file,
431 // applying the benefits more broadly.)
432 
433 // Note:  Keeping the data separate in passes (or "bands") allows the
434 // compressor to issue significantly shorter indexes for repeated data.
435 // The difference in zipped size is 4%, which is remarkable since the
436 // unzipped sizes are the same (only the byte order differs).
437 
438 // After moving similar data into bands, it becomes natural to delta-encode
439 // each band.  (This is especially useful if we sort the constant pool first.)
440 // Delta encoding saves an extra 5% in the output size (13% of the CP itself).
441 // Because a typical delta usees much less data than a byte, the savings after
442 // zipping is even better:  A zipped delta-encoded package is 8% smaller than
443 // a zipped non-delta-encoded package.  Thus, in the zipped file, a banded,
444 // delta-encoded constant pool saves over 11% (of the total file size) compared
445 // with a zipped unbanded file.
446 
447     void writeConstantPool() throws IOException {
448         IndexGroup cp = pkg.cp;
449 
450         if (verbose > 0)  Utils.log.info("Writing CP");
451 
452         for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
453             byte  tag   = ConstantPool.TAGS_IN_ORDER[k];
454             Index index = cp.getIndexByTag(tag);
455 
456             Entry[] cpMap = index.cpMap;
457             if (verbose > 0)
458                 Utils.log.info("Writing "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries...");
459 
460             if (optDumpBands) {
461                 try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) {
462                     printArrayTo(ps, cpMap, 0, cpMap.length);
463                 }
464             }
465 
466             switch (tag) {
467             case CONSTANT_Utf8:
468                 writeUtf8Bands(cpMap);
469                 break;
470             case CONSTANT_Integer:
471                 for (int i = 0; i < cpMap.length; i++) {
472                     NumberEntry e = (NumberEntry) cpMap[i];
473                     int x = ((Integer)e.numberValue()).intValue();
474                     cp_Int.putInt(x);
475                 }
476                 break;
477             case CONSTANT_Float:
478                 for (int i = 0; i < cpMap.length; i++) {
479                     NumberEntry e = (NumberEntry) cpMap[i];
480                     float fx = ((Float)e.numberValue()).floatValue();
481                     int x = Float.floatToIntBits(fx);
482                     cp_Float.putInt(x);
483                 }
484                 break;
485             case CONSTANT_Long:
486                 for (int i = 0; i < cpMap.length; i++) {
487                     NumberEntry e = (NumberEntry) cpMap[i];
488                     long x = ((Long)e.numberValue()).longValue();
489                     cp_Long_hi.putInt((int)(x >>> 32));
490                     cp_Long_lo.putInt((int)(x >>> 0));
491                 }
492                 break;
493             case CONSTANT_Double:
494                 for (int i = 0; i < cpMap.length; i++) {
495                     NumberEntry e = (NumberEntry) cpMap[i];
496                     double dx = ((Double)e.numberValue()).doubleValue();
497                     long x = Double.doubleToLongBits(dx);
498                     cp_Double_hi.putInt((int)(x >>> 32));
499                     cp_Double_lo.putInt((int)(x >>> 0));
500                 }
501                 break;
502             case CONSTANT_String:
503                 for (int i = 0; i < cpMap.length; i++) {
504                     StringEntry e = (StringEntry) cpMap[i];
505                     cp_String.putRef(e.ref);
506                 }
507                 break;
508             case CONSTANT_Class:
509                 for (int i = 0; i < cpMap.length; i++) {
510                     ClassEntry e = (ClassEntry) cpMap[i];
511                     cp_Class.putRef(e.ref);
512                 }
513                 break;
514             case CONSTANT_Signature:
515                 writeSignatureBands(cpMap);
516                 break;
517             case CONSTANT_NameandType:
518                 for (int i = 0; i < cpMap.length; i++) {
519                     DescriptorEntry e = (DescriptorEntry) cpMap[i];
520                     cp_Descr_name.putRef(e.nameRef);
521                     cp_Descr_type.putRef(e.typeRef);
522                 }
523                 break;
524             case CONSTANT_Fieldref:
525                 writeMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc);
526                 break;
527             case CONSTANT_Methodref:
528                 writeMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc);
529                 break;
530             case CONSTANT_InterfaceMethodref:
531                 writeMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
532                 break;
533             default:
534                 assert(false);
535             }
536         }
537     }
538 
539     void writeUtf8Bands(Entry[] cpMap) throws IOException {
540         if (cpMap.length == 0)
541             return;  // nothing to write
542 
543         // The first element must always be the empty string.
544         assert(cpMap[0].stringValue().equals(""));
545         final int SUFFIX_SKIP_1 = 1;
546         final int PREFIX_SKIP_2 = 2;
547 
548         // Fetch the char arrays, first of all.
549         char[][] chars = new char[cpMap.length][];
550         for (int i = 0; i < chars.length; i++) {
551             chars[i] = cpMap[i].stringValue().toCharArray();
552         }
553 
554         // First band:  Write lengths of shared prefixes.
555         int[] prefixes = new int[cpMap.length];  // includes 2 skipped zeroes
556         char[] prevChars = {};
557         for (int i = 0; i < chars.length; i++) {
558             int prefix = 0;
559             char[] curChars = chars[i];
560             int limit = Math.min(curChars.length, prevChars.length);
561             while (prefix < limit && curChars[prefix] == prevChars[prefix])
562                 prefix++;
563             prefixes[i] = prefix;
564             if (i >= PREFIX_SKIP_2)
565                 cp_Utf8_prefix.putInt(prefix);
566             else
567                 assert(prefix == 0);
568             prevChars = curChars;
569         }
570 
571         // Second band:  Write lengths of unshared suffixes.
572         // Third band:  Write the char values in the unshared suffixes.
573         for (int i = 0; i < chars.length; i++) {
574             char[] str = chars[i];
575             int prefix = prefixes[i];
576             int suffix = str.length - prefixes[i];
577             boolean isPacked = false;
578             if (suffix == 0) {
579                 // Zero suffix length is special flag to indicate
580                 // separate treatment in cp_Utf8_big bands.
581                 // This suffix length never occurs naturally,
582                 // except in the one case of a zero-length string.
583                 // (If it occurs, it is the first, due to sorting.)
584                 // The zero length string must, paradoxically, be
585                 // encoded as a zero-length cp_Utf8_big band.
586                 // This wastes exactly (& tolerably) one null byte.
587                 isPacked = (i >= SUFFIX_SKIP_1);
588                 // Do not bother to add an empty "(Utf8_big_0)" band.
589                 // Also, the initial empty string does not require a band.
590             } else if (optBigStrings && effort > 1 && suffix > 100) {
591                 int numWide = 0;
592                 for (int n = 0; n < suffix; n++) {
593                     if (str[prefix+n] > 127) {
594                         numWide++;
595                     }
596                 }
597                 if (numWide > 100) {
598                     // Try packing the chars with an alternate encoding.
599                     isPacked = tryAlternateEncoding(i, numWide, str, prefix);
600                 }
601             }
602             if (i < SUFFIX_SKIP_1) {
603                 // No output.
604                 assert(!isPacked);
605                 assert(suffix == 0);
606             } else if (isPacked) {
607                 // Mark packed string with zero-length suffix count.
608                 // This tells the unpacker to go elsewhere for the suffix bits.
609                 // Fourth band:  Write unshared suffix with alternate coding.
610                 cp_Utf8_suffix.putInt(0);
611                 cp_Utf8_big_suffix.putInt(suffix);
612             } else {
613                 assert(suffix != 0);  // would be ambiguous
614                 // Normal string.  Save suffix in third and fourth bands.
615                 cp_Utf8_suffix.putInt(suffix);
616                 for (int n = 0; n < suffix; n++) {
617                     int ch = str[prefix+n];
618                     cp_Utf8_chars.putInt(ch);
619                 }
620             }
621         }
622         if (verbose > 0) {
623             int normCharCount = cp_Utf8_chars.length();
624             int packCharCount = cp_Utf8_big_chars.length();
625             int charCount = normCharCount + packCharCount;
626             Utils.log.info("Utf8string #CHARS="+charCount+" #PACKEDCHARS="+packCharCount);
627         }
628     }
629 
630     private boolean tryAlternateEncoding(int i, int numWide,
631                                          char[] str, int prefix) {
632         int suffix = str.length - prefix;
633         int[] cvals = new int[suffix];
634         for (int n = 0; n < suffix; n++) {
635             cvals[n] = str[prefix+n];
636         }
637         CodingChooser cc = getCodingChooser();
638         Coding bigRegular = cp_Utf8_big_chars.regularCoding;
639         String bandName = "(Utf8_big_"+i+")";
640         int[] sizes = { 0, 0 };
641         final int BYTE_SIZE = CodingChooser.BYTE_SIZE;
642         final int ZIP_SIZE = CodingChooser.ZIP_SIZE;
643         if (verbose > 1 || cc.verbose > 1) {
644             Utils.log.fine("--- chooseCoding "+bandName);
645         }
646         CodingMethod special = cc.choose(cvals, bigRegular, sizes);
647         Coding charRegular = cp_Utf8_chars.regularCoding;
648         if (verbose > 1)
649             Utils.log.fine("big string["+i+"] len="+suffix+" #wide="+numWide+" size="+sizes[BYTE_SIZE]+"/z="+sizes[ZIP_SIZE]+" coding "+special);
650         if (special != charRegular) {
651             int specialZipSize = sizes[ZIP_SIZE];
652             int[] normalSizes = cc.computeSize(charRegular, cvals);
653             int normalZipSize = normalSizes[ZIP_SIZE];
654             int minWin = Math.max(5, normalZipSize/1000);
655             if (verbose > 1)
656                 Utils.log.fine("big string["+i+"] normalSize="+normalSizes[BYTE_SIZE]+"/z="+normalSizes[ZIP_SIZE]+" win="+(specialZipSize<normalZipSize-minWin));
657             if (specialZipSize < normalZipSize-minWin) {
658                 IntBand big = cp_Utf8_big_chars.newIntBand(bandName);
659                 big.initializeValues(cvals);
660                 return true;
661             }
662         }
663         return false;
664     }
665 
666     void writeSignatureBands(Entry[] cpMap) throws IOException {
667         for (int i = 0; i < cpMap.length; i++) {
668             SignatureEntry e = (SignatureEntry) cpMap[i];
669             cp_Signature_form.putRef(e.formRef);
670             for (int j = 0; j < e.classRefs.length; j++) {
671                 cp_Signature_classes.putRef(e.classRefs[j]);
672             }
673         }
674     }
675 
676     void writeMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException {
677         for (int i = 0; i < cpMap.length; i++) {
678             MemberEntry e = (MemberEntry) cpMap[i];
679             cp_class.putRef(e.classRef);
680             cp_desc.putRef(e.descRef);
681         }
682     }
683 
684     void writeFiles() throws IOException {
685         int numFiles = pkg.files.size();
686         if (numFiles == 0)  return;
687         int options = archiveOptions;
688         boolean haveSizeHi  = testBit(options, AO_HAVE_FILE_SIZE_HI);
689         boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
690         boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
691         if (!haveOptions) {
692             for (File file : pkg.files) {
693                 if (file.isClassStub()) {
694                     haveOptions = true;
695                     options |= AO_HAVE_FILE_OPTIONS;
696                     archiveOptions = options;
697                     break;
698                 }
699             }
700         }
701         if (haveSizeHi || haveModtime || haveOptions || !pkg.files.isEmpty()) {
702             options |= AO_HAVE_FILE_HEADERS;
703             archiveOptions = options;
704         }
705         for (File file : pkg.files) {
706             file_name.putRef(file.name);
707             long len = file.getFileLength();
708             file_size_lo.putInt((int)len);
709             if (haveSizeHi)
710                 file_size_hi.putInt((int)(len >>> 32));
711             if (haveModtime)
712                 file_modtime.putInt(file.modtime - pkg.default_modtime);
713             if (haveOptions)
714                 file_options.putInt(file.options);
715             file.writeTo(file_bits.collectorStream());
716             if (verbose > 1)
717                 Utils.log.fine("Wrote "+len+" bytes of "+file.name.stringValue());
718         }
719         if (verbose > 0)
720             Utils.log.info("Wrote "+numFiles+" resource files");
721     }
722 
723     @SuppressWarnings("unchecked")
724     void collectAttributeLayouts() {
725         maxFlags = new int[ATTR_CONTEXT_LIMIT];
726         allLayouts = new FixedList<>(ATTR_CONTEXT_LIMIT);
727         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
728             allLayouts.set(i, new HashMap<Attribute.Layout, int[]>());
729         }
730         // Collect maxFlags and allLayouts.
731         for (Class cls : pkg.classes) {
732             visitAttributeLayoutsIn(ATTR_CONTEXT_CLASS, cls);
733             for (Class.Field f : cls.getFields()) {
734                 visitAttributeLayoutsIn(ATTR_CONTEXT_FIELD, f);
735             }
736             for (Class.Method m : cls.getMethods()) {
737                 visitAttributeLayoutsIn(ATTR_CONTEXT_METHOD, m);
738                 if (m.code != null) {
739                     visitAttributeLayoutsIn(ATTR_CONTEXT_CODE, m.code);
740                 }
741             }
742         }
743         // If there are many species of attributes, use 63-bit flags.
744         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
745             int nl = allLayouts.get(i).size();
746             boolean haveLongFlags = haveFlagsHi(i);
747             final int TOO_MANY_ATTRS = 32 /*int flag size*/
748                 - 12 /*typical flag bits in use*/
749                 + 4  /*typical number of OK overflows*/;
750             if (nl >= TOO_MANY_ATTRS) {  // heuristic
751                 int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+i);
752                 archiveOptions |= mask;
753                 haveLongFlags = true;
754                 if (verbose > 0)
755                    Utils.log.info("Note: Many "+Attribute.contextName(i)+" attributes forces 63-bit flags");
756             }
757             if (verbose > 1) {
758                 Utils.log.fine(Attribute.contextName(i)+".maxFlags = 0x"+Integer.toHexString(maxFlags[i]));
759                 Utils.log.fine(Attribute.contextName(i)+".#layouts = "+nl);
760             }
761             assert(haveFlagsHi(i) == haveLongFlags);
762         }
763         initAttrIndexLimit();
764 
765         // Standard indexes can never conflict with flag bits.  Assert it.
766         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
767             assert((attrFlagMask[i] & maxFlags[i]) == 0);
768         }
769         // Collect counts for both predefs. and custom defs.
770         // Decide on custom, local attribute definitions.
771         backCountTable = new HashMap<>();
772         attrCounts = new int[ATTR_CONTEXT_LIMIT][];
773         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
774             // Now the remaining defs in allLayouts[i] need attr. indexes.
775             // Fill up unused flag bits with new defs.
776             // Unused bits are those which are not used by predefined attrs,
777             // and which are always clear in the classfiles.
778             long avHiBits = ~(maxFlags[i] | attrFlagMask[i]);
779             assert(attrIndexLimit[i] > 0);
780             assert(attrIndexLimit[i] < 64);  // all bits fit into a Java long
781             avHiBits &= (1L<<attrIndexLimit[i])-1;
782             int nextLoBit = 0;
783             Map<Attribute.Layout, int[]> defMap = allLayouts.get(i);
784             Map.Entry[] layoutsAndCounts = new Map.Entry[defMap.size()];
785             defMap.entrySet().toArray(layoutsAndCounts);
786             // Sort by count, most frequent first.
787             // Predefs. participate in this sort, though it does not matter.
788             Arrays.sort(layoutsAndCounts, new Comparator<Object>() {
789                 public int compare(Object o0, Object o1) {
790                     Map.Entry e0 = (Map.Entry) o0;
791                     Map.Entry e1 = (Map.Entry) o1;
792                     // Primary sort key is count, reversed.
793                     int r = - ( ((int[])e0.getValue())[0]
794                               - ((int[])e1.getValue())[0] );
795                     if (r != 0)  return r;
796                     return ((Comparable)e0.getKey()).compareTo(e1.getKey());
797                 }
798             });
799             attrCounts[i] = new int[attrIndexLimit[i]+layoutsAndCounts.length];
800             for (int j = 0; j < layoutsAndCounts.length; j++) {
801                 Map.Entry e = layoutsAndCounts[j];
802                 Attribute.Layout def = (Attribute.Layout) e.getKey();
803                 int count = ((int[])e.getValue())[0];
804                 int index;
805                 Integer predefIndex = attrIndexTable.get(def);
806                 if (predefIndex != null) {
807                     // The index is already set.
808                     index = predefIndex.intValue();
809                 } else if (avHiBits != 0) {
810                     while ((avHiBits & 1) == 0) {
811                         avHiBits >>>= 1;
812                         nextLoBit += 1;
813                     }
814                     avHiBits -= 1;  // clear low bit; we are using it now
815                     // Update attrIndexTable:
816                     index = setAttributeLayoutIndex(def, nextLoBit);
817                 } else {
818                     // Update attrIndexTable:
819                     index = setAttributeLayoutIndex(def, ATTR_INDEX_OVERFLOW);
820                 }
821 
822                 // Now that we know the index, record the count of this def.
823                 attrCounts[i][index] = count;
824 
825                 // For all callables in the def, keep a tally of back-calls.
826                 Attribute.Layout.Element[] cbles = def.getCallables();
827                 final int[] bc = new int[cbles.length];
828                 for (int k = 0; k < cbles.length; k++) {
829                     assert(cbles[k].kind == Attribute.EK_CBLE);
830                     if (!cbles[k].flagTest(Attribute.EF_BACK)) {
831                         bc[k] = -1;  // no count to accumulate here
832                     }
833                 }
834                 backCountTable.put(def, bc);
835 
836                 if (predefIndex == null) {
837                     // Make sure the package CP can name the local attribute.
838                     Entry ne = ConstantPool.getUtf8Entry(def.name());
839                     String layout = def.layoutForPackageMajver(getPackageMajver());
840                     Entry le = ConstantPool.getUtf8Entry(layout);
841                     requiredEntries.add(ne);
842                     requiredEntries.add(le);
843                     if (verbose > 0) {
844                         if (index < attrIndexLimit[i])
845                            Utils.log.info("Using free flag bit 1<<"+index+" for "+count+" occurrences of "+def);
846                         else
847                             Utils.log.info("Using overflow index "+index+" for "+count+" occurrences of "+def);
848                     }
849                 }
850             }
851         }
852         // Later, when emitting attr_definition_bands, we will look at
853         // attrDefSeen and attrDefs at position 32/63 and beyond.
854         // The attrIndexTable will provide elements of xxx_attr_indexes bands.
855 
856         // Done with scratch variables:
857         maxFlags = null;
858         allLayouts = null;
859     }
860 
861     // Scratch variables for processing attributes and flags.
862     int[] maxFlags;
863     List<Map<Attribute.Layout, int[]>> allLayouts;
864 
865     void visitAttributeLayoutsIn(int ctype, Attribute.Holder h) {
866         // Make note of which flags appear in the class file.
867         // Set them in maxFlags.
868         maxFlags[ctype] |= h.flags;
869         for (Attribute a : h.getAttributes()) {
870             Attribute.Layout def = a.layout();
871             Map<Attribute.Layout, int[]> defMap = allLayouts.get(ctype);
872             int[] count = defMap.get(def);
873             if (count == null) {
874                 defMap.put(def, count = new int[1]);
875             }
876             if (count[0] < Integer.MAX_VALUE) {
877                 count[0] += 1;
878             }
879         }
880     }
881 
882     Attribute.Layout[] attrDefsWritten;
883 
884     @SuppressWarnings("unchecked")
885     void writeAttrDefs() throws IOException {
886         List<Object[]> defList = new ArrayList<>();
887         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
888             int limit = attrDefs.get(i).size();
889             for (int j = 0; j < limit; j++) {
890                 int header = i;  // ctype
891                 if (j < attrIndexLimit[i]) {
892                     header |= ((j + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT);
893                     assert(header < 0x100);  // must fit into a byte
894                     // (...else header is simply ctype, with zero high bits.)
895                     if (!testBit(attrDefSeen[i], 1L<<j)) {
896                         // either undefined or predefined; nothing to write
897                         continue;
898                     }
899                 }
900                 Attribute.Layout def = attrDefs.get(i).get(j);
901                 defList.add(new Object[]{ Integer.valueOf(header), def });
902                 assert(Integer.valueOf(j).equals(attrIndexTable.get(def)));
903             }
904         }
905         // Sort the new attr defs into some "natural" order.
906         int numAttrDefs = defList.size();
907         Object[][] defs = new Object[numAttrDefs][];
908         defList.toArray(defs);
909         Arrays.sort(defs, new Comparator() {
910             public int compare(Object o0, Object o1) {
911                 Object[] a0 = (Object[]) o0;
912                 Object[] a1 = (Object[]) o1;
913                 // Primary sort key is attr def header.
914                 int r = ((Comparable)a0[0]).compareTo(a1[0]);
915                 if (r != 0)  return r;
916                 Object ind0 = attrIndexTable.get(a0[1]);
917                 Object ind1 = attrIndexTable.get(a1[1]);
918                 // Secondary sort key is attribute index.
919                 // (This must be so, in order to keep overflow attr order.)
920                 assert(ind0 != null);
921                 assert(ind1 != null);
922                 return ((Comparable)ind0).compareTo(ind1);
923             }
924         });
925         attrDefsWritten = new Attribute.Layout[numAttrDefs];
926         try (PrintStream dump = !optDumpBands ? null
927                  : new PrintStream(getDumpStream(attr_definition_headers, ".def")))
928         {
929             int[] indexForDebug = Arrays.copyOf(attrIndexLimit, ATTR_CONTEXT_LIMIT);
930             for (int i = 0; i < defs.length; i++) {
931                 int header = ((Integer)defs[i][0]).intValue();
932                 Attribute.Layout def = (Attribute.Layout) defs[i][1];
933                 attrDefsWritten[i] = def;
934                 assert((header & ADH_CONTEXT_MASK) == def.ctype());
935                 attr_definition_headers.putByte(header);
936                 attr_definition_name.putRef(ConstantPool.getUtf8Entry(def.name()));
937                 String layout = def.layoutForPackageMajver(getPackageMajver());
938                 attr_definition_layout.putRef(ConstantPool.getUtf8Entry(layout));
939                 // Check that we are transmitting that correct attribute index:
940                 boolean debug = false;
941                 assert(debug = true);
942                 if (debug) {
943                     int hdrIndex = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
944                     if (hdrIndex < 0)  hdrIndex = indexForDebug[def.ctype()]++;
945                     int realIndex = (attrIndexTable.get(def)).intValue();
946                     assert(hdrIndex == realIndex);
947                 }
948                 if (dump != null) {
949                     int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
950                     dump.println(index+" "+def);
951                 }
952             }
953         }
954     }
955 
956     void writeAttrCounts() throws IOException {
957         // Write the four xxx_attr_calls bands.
958         for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
959             MultiBand xxx_attr_bands = attrBands[ctype];
960             IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS);
961             Attribute.Layout[] defs = new Attribute.Layout[attrDefs.get(ctype).size()];
962             attrDefs.get(ctype).toArray(defs);
963             for (boolean predef = true; ; predef = false) {
964                 for (int ai = 0; ai < defs.length; ai++) {
965                     Attribute.Layout def = defs[ai];
966                     if (def == null)  continue;  // unused index
967                     if (predef != isPredefinedAttr(ctype, ai))
968                         continue;  // wrong pass
969                     int totalCount = attrCounts[ctype][ai];
970                     if (totalCount == 0)
971                         continue;  // irrelevant
972                     int[] bc = backCountTable.get(def);
973                     for (int j = 0; j < bc.length; j++) {
974                         if (bc[j] >= 0) {
975                             int backCount = bc[j];
976                             bc[j] = -1;  // close out; do not collect further counts
977                             xxx_attr_calls.putInt(backCount);
978                             assert(def.getCallables()[j].flagTest(Attribute.EF_BACK));
979                         } else {
980                             assert(!def.getCallables()[j].flagTest(Attribute.EF_BACK));
981                         }
982                     }
983                 }
984                 if (!predef)  break;
985             }
986         }
987     }
988 
989     void trimClassAttributes() {
990         for (Class cls : pkg.classes) {
991             // Replace "obvious" SourceFile attrs by null.
992             cls.minimizeSourceFile();
993         }
994     }
995 
996     void collectInnerClasses() {
997         // Capture inner classes, removing them from individual classes.
998         // Irregular inner classes must stay local, though.
999         Map<ClassEntry, InnerClass> allICMap = new HashMap<>();
1000         // First, collect a consistent global set.
1001         for (Class cls : pkg.classes) {
1002             if (!cls.hasInnerClasses())  continue;
1003             for (InnerClass ic : cls.getInnerClasses()) {
1004                 InnerClass pic = allICMap.put(ic.thisClass, ic);
1005                 if (pic != null && !pic.equals(ic) && pic.predictable) {
1006                     // Different ICs.  Choose the better to make global.
1007                     allICMap.put(pic.thisClass, pic);
1008                 }
1009             }
1010         }
1011 
1012         InnerClass[] allICs = new InnerClass[allICMap.size()];
1013         allICMap.values().toArray(allICs);
1014         allICMap = null;  // done with it
1015 
1016         // Note: The InnerClasses attribute must be in a valid order,
1017         // so that A$B always occurs earlier than A$B$C.  This is an
1018         // important side-effect of sorting lexically by class name.
1019         Arrays.sort(allICs);  // put in canonical order
1020         pkg.setAllInnerClasses(Arrays.asList(allICs));
1021 
1022         // Next, empty out of every local set the consistent entries.
1023         // Calculate whether there is any remaining need to have a local
1024         // set, and whether it needs to be locked.
1025         for (Class cls : pkg.classes) {
1026             cls.minimizeLocalICs();
1027         }
1028     }
1029 
1030     void writeInnerClasses() throws IOException {
1031         for (InnerClass ic : pkg.getAllInnerClasses()) {
1032             int flags = ic.flags;
1033             assert((flags & ACC_IC_LONG_FORM) == 0);
1034             if (!ic.predictable) {
1035                 flags |= ACC_IC_LONG_FORM;
1036             }
1037             ic_this_class.putRef(ic.thisClass);
1038             ic_flags.putInt(flags);
1039             if (!ic.predictable) {
1040                 ic_outer_class.putRef(ic.outerClass);
1041                 ic_name.putRef(ic.name);
1042             }
1043         }
1044     }
1045 
1046     /** If there are any extra InnerClasses entries to write which are
1047      *  not already implied by the global table, put them into a
1048      *  local attribute.  This is expected to be rare.
1049      */
1050     void writeLocalInnerClasses(Class cls) throws IOException {
1051         List<InnerClass> localICs = cls.getInnerClasses();
1052         class_InnerClasses_N.putInt(localICs.size());
1053         for(InnerClass ic : localICs) {
1054             class_InnerClasses_RC.putRef(ic.thisClass);
1055             // Is it redundant with the global version?
1056             if (ic.equals(pkg.getGlobalInnerClass(ic.thisClass))) {
1057                 // A zero flag means copy a global IC here.
1058                 class_InnerClasses_F.putInt(0);
1059             } else {
1060                 int flags = ic.flags;
1061                 if (flags == 0)
1062                     flags = ACC_IC_LONG_FORM;  // force it to be non-zero
1063                 class_InnerClasses_F.putInt(flags);
1064                 class_InnerClasses_outer_RCN.putRef(ic.outerClass);
1065                 class_InnerClasses_name_RUN.putRef(ic.name);
1066             }
1067         }
1068     }
1069 
1070     void writeClassesAndByteCodes() throws IOException {
1071         Class[] classes = new Class[pkg.classes.size()];
1072         pkg.classes.toArray(classes);
1073         // Note:  This code respects the order in which caller put classes.
1074         if (verbose > 0)
1075             Utils.log.info("  ...scanning "+classes.length+" classes...");
1076 
1077         int nwritten = 0;
1078         for (int i = 0; i < classes.length; i++) {
1079             // Collect the class body, sans bytecodes.
1080             Class cls = classes[i];
1081             if (verbose > 1)
1082                 Utils.log.fine("Scanning "+cls);
1083 
1084             ClassEntry   thisClass  = cls.thisClass;
1085             ClassEntry   superClass = cls.superClass;
1086             ClassEntry[] interfaces = cls.interfaces;
1087             // Encode rare case of null superClass as thisClass:
1088             assert(superClass != thisClass);  // bad class file!?
1089             if (superClass == null)  superClass = thisClass;
1090             class_this.putRef(thisClass);
1091             class_super.putRef(superClass);
1092             class_interface_count.putInt(cls.interfaces.length);
1093             for (int j = 0; j < interfaces.length; j++) {
1094                 class_interface.putRef(interfaces[j]);
1095             }
1096 
1097             writeMembers(cls);
1098             writeAttrs(ATTR_CONTEXT_CLASS, cls, cls);
1099 
1100             nwritten++;
1101             if (verbose > 0 && (nwritten % 1000) == 0)
1102                 Utils.log.info("Have scanned "+nwritten+" classes...");
1103         }
1104     }
1105 
1106     void writeMembers(Class cls) throws IOException {
1107         List<Class.Field> fields = cls.getFields();
1108         class_field_count.putInt(fields.size());
1109         for (Class.Field f : fields) {
1110             field_descr.putRef(f.getDescriptor());
1111             writeAttrs(ATTR_CONTEXT_FIELD, f, cls);
1112         }
1113 
1114         List<Class.Method> methods = cls.getMethods();
1115         class_method_count.putInt(methods.size());
1116         for (Class.Method m : methods) {
1117             method_descr.putRef(m.getDescriptor());
1118             writeAttrs(ATTR_CONTEXT_METHOD, m, cls);
1119             assert((m.code != null) == (m.getAttribute(attrCodeEmpty) != null));
1120             if (m.code != null) {
1121                 writeCodeHeader(m.code);
1122                 writeByteCodes(m.code);
1123             }
1124         }
1125     }
1126 
1127     void writeCodeHeader(Code c) throws IOException {
1128         boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS);
1129         int na = c.attributeSize();
1130         int sc = shortCodeHeader(c);
1131         if (!attrsOK && na > 0)
1132             // We must write flags, and can only do so for long headers.
1133             sc = LONG_CODE_HEADER;
1134         if (verbose > 2) {
1135             int siglen = c.getMethod().getArgumentSize();
1136             Utils.log.fine("Code sizes info "+c.max_stack+" "+c.max_locals+" "+c.getHandlerCount()+" "+siglen+" "+na+(sc > 0 ? " SHORT="+sc : ""));
1137         }
1138         code_headers.putByte(sc);
1139         if (sc == LONG_CODE_HEADER) {
1140             code_max_stack.putInt(c.getMaxStack());
1141             code_max_na_locals.putInt(c.getMaxNALocals());
1142             code_handler_count.putInt(c.getHandlerCount());
1143         } else {
1144             assert(attrsOK || na == 0);
1145             assert(c.getHandlerCount() < shortCodeHeader_h_limit);
1146         }
1147         writeCodeHandlers(c);
1148         if (sc == LONG_CODE_HEADER || attrsOK)
1149             writeAttrs(ATTR_CONTEXT_CODE, c, c.thisClass());
1150     }
1151 
1152     void writeCodeHandlers(Code c) throws IOException {
1153         int sum, del;
1154         for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1155             code_handler_class_RCN.putRef(c.handler_class[j]); // null OK
1156             // Encode end as offset from start, and catch as offset from end,
1157             // because they are strongly correlated.
1158             sum = c.encodeBCI(c.handler_start[j]);
1159             code_handler_start_P.putInt(sum);
1160             del = c.encodeBCI(c.handler_end[j]) - sum;
1161             code_handler_end_PO.putInt(del);
1162             sum += del;
1163             del = c.encodeBCI(c.handler_catch[j]) - sum;
1164             code_handler_catch_PO.putInt(del);
1165         }
1166     }
1167 
1168     // Generic routines for writing attributes and flags of
1169     // classes, fields, methods, and codes.
1170     void writeAttrs(int ctype,
1171                     final Attribute.Holder h,
1172                     Class cls) throws IOException {
1173         MultiBand xxx_attr_bands = attrBands[ctype];
1174         IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1175         IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1176         boolean haveLongFlags = haveFlagsHi(ctype);
1177         assert(attrIndexLimit[ctype] == (haveLongFlags? 63: 32));
1178         if (h.attributes == null) {
1179             xxx_flags_lo.putInt(h.flags);  // no extra bits to set here
1180             if (haveLongFlags)
1181                 xxx_flags_hi.putInt(0);
1182             return;
1183         }
1184         if (verbose > 3)
1185             Utils.log.fine("Transmitting attrs for "+h+" flags="+Integer.toHexString(h.flags));
1186 
1187         long flagMask = attrFlagMask[ctype];  // which flags are attr bits?
1188         long flagsToAdd = 0;
1189         int overflowCount = 0;
1190         for (Attribute a : h.attributes) {
1191             Attribute.Layout def = a.layout();
1192             int index = (attrIndexTable.get(def)).intValue();
1193             assert(attrDefs.get(ctype).get(index) == def);
1194             if (verbose > 3)
1195                 Utils.log.fine("add attr @"+index+" "+a+" in "+h);
1196             if (index < attrIndexLimit[ctype] && testBit(flagMask, 1L<<index)) {
1197                 if (verbose > 3)
1198                     Utils.log.fine("Adding flag bit 1<<"+index+" in "+Long.toHexString(flagMask));
1199                 assert(!testBit(h.flags, 1L<<index));
1200                 flagsToAdd |= (1L<<index);
1201                 flagMask -= (1L<<index);  // do not use this bit twice here
1202             } else {
1203                 // an overflow attr.
1204                 flagsToAdd |= (1L<<X_ATTR_OVERFLOW);
1205                 overflowCount += 1;
1206                 if (verbose > 3)
1207                     Utils.log.fine("Adding overflow attr #"+overflowCount);
1208                 IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES);
1209                 xxx_attr_indexes.putInt(index);
1210                 // System.out.println("overflow @"+index);
1211             }
1212             if (def.bandCount == 0) {
1213                 if (def == attrInnerClassesEmpty) {
1214                     // Special logic to write this attr.
1215                     writeLocalInnerClasses((Class) h);
1216                     continue;
1217                 }
1218                 // Empty attr; nothing more to write here.
1219                 continue;
1220             }
1221             assert(a.fixups == null);
1222             final Band[] ab = attrBandTable.get(def);
1223             assert(ab != null);
1224             assert(ab.length == def.bandCount);
1225             final int[] bc = backCountTable.get(def);
1226             assert(bc != null);
1227             assert(bc.length == def.getCallables().length);
1228             // Write one attribute of type def into ab.
1229             if (verbose > 2)  Utils.log.fine("writing "+a+" in "+h);
1230             boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1231             if (isCV)  setConstantValueIndex((Class.Field)h);
1232             a.parse(cls, a.bytes(), 0, a.size(),
1233                       new Attribute.ValueStream() {
1234                 public void putInt(int bandIndex, int value) {
1235                     ((IntBand) ab[bandIndex]).putInt(value);
1236                 }
1237                 public void putRef(int bandIndex, Entry ref) {
1238                     ((CPRefBand) ab[bandIndex]).putRef(ref);
1239                 }
1240                 public int encodeBCI(int bci) {
1241                     Code code = (Code) h;
1242                     return code.encodeBCI(bci);
1243                 }
1244                 public void noteBackCall(int whichCallable) {
1245                     assert(bc[whichCallable] >= 0);
1246                     bc[whichCallable] += 1;
1247                 }
1248             });
1249             if (isCV)  setConstantValueIndex(null);  // clean up
1250         }
1251 
1252         if (overflowCount > 0) {
1253             IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT);
1254             xxx_attr_count.putInt(overflowCount);
1255         }
1256 
1257         xxx_flags_lo.putInt(h.flags | (int)flagsToAdd);
1258         if (haveLongFlags)
1259             xxx_flags_hi.putInt((int)(flagsToAdd >>> 32));
1260         else
1261             assert((flagsToAdd >>> 32) == 0);
1262         assert((h.flags & flagsToAdd) == 0)
1263             : (h+".flags="
1264                 +Integer.toHexString(h.flags)+"^"
1265                 +Long.toHexString(flagsToAdd));
1266     }
1267 
1268     // temporary scratch variables for processing code blocks
1269     private Code                 curCode;
1270     private Class                curClass;
1271     private Entry[] curCPMap;
1272     private void beginCode(Code c) {
1273         assert(curCode == null);
1274         curCode = c;
1275         curClass = c.m.thisClass();
1276         curCPMap = c.getCPMap();
1277     }
1278     private void endCode() {
1279         curCode = null;
1280         curClass = null;
1281         curCPMap = null;
1282     }
1283 
1284     // Return an _invokeinit_op variant, if the instruction matches one,
1285     // else -1.
1286     private int initOpVariant(Instruction i, Entry newClass) {
1287         if (i.getBC() != _invokespecial)  return -1;
1288         MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1289         if ("<init>".equals(ref.descRef.nameRef.stringValue()) == false)
1290             return -1;
1291         ClassEntry refClass = ref.classRef;
1292         if (refClass == curClass.thisClass)
1293             return _invokeinit_op+_invokeinit_self_option;
1294         if (refClass == curClass.superClass)
1295             return _invokeinit_op+_invokeinit_super_option;
1296         if (refClass == newClass)
1297             return _invokeinit_op+_invokeinit_new_option;
1298         return -1;
1299     }
1300 
1301     // Return a _self_linker_op variant, if the instruction matches one,
1302     // else -1.
1303     private int selfOpVariant(Instruction i) {
1304         int bc = i.getBC();
1305         if (!(bc >= _first_linker_op && bc <= _last_linker_op))  return -1;
1306         MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1307         ClassEntry refClass = ref.classRef;
1308         int self_bc = _self_linker_op + (bc - _first_linker_op);
1309         if (refClass == curClass.thisClass)
1310             return self_bc;
1311         if (refClass == curClass.superClass)
1312             return self_bc + _self_linker_super_flag;
1313         return -1;
1314     }
1315 
1316     void writeByteCodes(Code code) throws IOException {
1317         beginCode(code);
1318         IndexGroup cp = pkg.cp;
1319 
1320         // true if the previous instruction is an aload to absorb
1321         boolean prevAload = false;
1322 
1323         // class of most recent new; helps compress <init> calls
1324         Entry newClass = null;
1325 
1326         for (Instruction i = code.instructionAt(0); i != null; i = i.next()) {
1327             // %%% Add a stress mode which issues _ref/_byte_escape.
1328             if (verbose > 3)  Utils.log.fine(i.toString());
1329 
1330             if (i.isNonstandard()
1331                 && (!p200.getBoolean(Utils.COM_PREFIX+"invokedynamic")
1332                     || i.getBC() != _xxxunusedxxx)) {
1333                 // Crash and burn with a complaint if there are funny
1334                 // bytecodes in this class file.
1335                 String complaint = code.getMethod()
1336                     +" contains an unrecognized bytecode "+i
1337                     +"; please use the pass-file option on this class.";
1338                 Utils.log.warning(complaint);
1339                 throw new IOException(complaint);
1340             }
1341 
1342             if (i.isWide()) {
1343                 if (verbose > 1) {
1344                     Utils.log.fine("_wide opcode in "+code);
1345                     Utils.log.fine(i.toString());
1346                 }
1347                 bc_codes.putByte(_wide);
1348                 codeHist[_wide]++;
1349             }
1350 
1351             int bc = i.getBC();
1352 
1353             // Begin "bc_linker" compression.
1354             if (bc == _aload_0) {
1355                 // Try to group aload_0 with a following operation.
1356                 Instruction ni = code.instructionAt(i.getNextPC());
1357                 if (selfOpVariant(ni) >= 0) {
1358                     prevAload = true;
1359                     continue;
1360                 }
1361             }
1362 
1363             // Test for <init> invocations:
1364             int init_bc = initOpVariant(i, newClass);
1365             if (init_bc >= 0) {
1366                 if (prevAload) {
1367                     // get rid of it
1368                     bc_codes.putByte(_aload_0);
1369                     codeHist[_aload_0]++;
1370                     prevAload = false;  //used up
1371                 }
1372                 // Write special bytecode.
1373                 bc_codes.putByte(init_bc);
1374                 codeHist[init_bc]++;
1375                 MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1376                 // Write operand to a separate band.
1377                 int coding = cp.getOverloadingIndex(ref);
1378                 bc_initref.putInt(coding);
1379                 continue;
1380             }
1381 
1382             int self_bc = selfOpVariant(i);
1383             if (self_bc >= 0) {
1384                 boolean isField = Instruction.isFieldOp(bc);
1385                 boolean isSuper = (self_bc >= _self_linker_op+_self_linker_super_flag);
1386                 boolean isAload = prevAload;
1387                 prevAload = false;  //used up
1388                 if (isAload)
1389                     self_bc += _self_linker_aload_flag;
1390                 // Write special bytecode.
1391                 bc_codes.putByte(self_bc);
1392                 codeHist[self_bc]++;
1393                 // Write field or method ref to a separate band.
1394                 MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1395                 CPRefBand bc_which = selfOpRefBand(self_bc);
1396                 Index which_ix = cp.getMemberIndex(ref.tag, ref.classRef);
1397                 bc_which.putRef(ref, which_ix);
1398                 continue;
1399             }
1400             assert(!prevAload);
1401             // End "bc_linker" compression.
1402 
1403             // Normal bytecode.
1404             codeHist[bc]++;
1405             switch (bc) {
1406             case _tableswitch: // apc:  (df, lo, hi, (hi-lo+1)*(label))
1407             case _lookupswitch: // apc:  (df, nc, nc*(case, label))
1408                 bc_codes.putByte(bc);
1409                 Instruction.Switch isw = (Instruction.Switch) i;
1410                 // Note that we do not write the alignment bytes.
1411                 int apc = isw.getAlignedPC();
1412                 int npc = isw.getNextPC();
1413                 // write a length specification into the bytecode stream
1414                 int caseCount = isw.getCaseCount();
1415                 bc_case_count.putInt(caseCount);
1416                 putLabel(bc_label, code, i.getPC(), isw.getDefaultLabel());
1417                 for (int j = 0; j < caseCount; j++) {
1418                     putLabel(bc_label, code, i.getPC(), isw.getCaseLabel(j));
1419                 }
1420                 // Transmit case values in their own band.
1421                 if (bc == _tableswitch) {
1422                     bc_case_value.putInt(isw.getCaseValue(0));
1423                 } else {
1424                     for (int j = 0; j < caseCount; j++) {
1425                         bc_case_value.putInt(isw.getCaseValue(j));
1426                     }
1427                 }
1428                 // Done with the switch.
1429                 continue;
1430             }
1431 
1432             switch (bc) {
1433             case _xxxunusedxxx:  // %%% pretend this is invokedynamic
1434                 {
1435                     i.setNonstandardLength(3);
1436                     int refx = i.getShortAt(1);
1437                     Entry ref = (refx == 0)? null: curCPMap[refx];
1438                     // transmit the opcode, carefully:
1439                     bc_codes.putByte(_byte_escape);
1440                     bc_escsize.putInt(1);     // one byte of opcode
1441                     bc_escbyte.putByte(bc);   // the opcode
1442                     // transmit the CP reference, carefully:
1443                     bc_codes.putByte(_ref_escape);
1444                     bc_escrefsize.putInt(2);  // two bytes of ref
1445                     bc_escref.putRef(ref);    // the ref
1446                     continue;
1447                 }
1448             }
1449 
1450             int branch = i.getBranchLabel();
1451             if (branch >= 0) {
1452                 bc_codes.putByte(bc);
1453                 putLabel(bc_label, code, i.getPC(), branch);
1454                 continue;
1455             }
1456             Entry ref = i.getCPRef(curCPMap);
1457             if (ref != null) {
1458                 if (bc == _new)  newClass = ref;
1459                 if (bc == _ldc)  ldcHist[ref.tag]++;
1460                 CPRefBand bc_which;
1461                 int vbc = bc;
1462                 switch (i.getCPTag()) {
1463                 case CONSTANT_Literal:
1464                     switch (ref.tag) {
1465                     case CONSTANT_Integer:
1466                         bc_which = bc_intref;
1467                         switch (bc) {
1468                         case _ldc:    vbc = _ildc; break;
1469                         case _ldc_w:  vbc = _ildc_w; break;
1470                         default:      assert(false);
1471                         }
1472                         break;
1473                     case CONSTANT_Float:
1474                         bc_which = bc_floatref;
1475                         switch (bc) {
1476                         case _ldc:    vbc = _fldc; break;
1477                         case _ldc_w:  vbc = _fldc_w; break;
1478                         default:      assert(false);
1479                         }
1480                         break;
1481                     case CONSTANT_Long:
1482                         bc_which = bc_longref;
1483                         assert(bc == _ldc2_w);
1484                         vbc = _lldc2_w;
1485                         break;
1486                     case CONSTANT_Double:
1487                         bc_which = bc_doubleref;
1488                         assert(bc == _ldc2_w);
1489                         vbc = _dldc2_w;
1490                         break;
1491                     case CONSTANT_String:
1492                         bc_which = bc_stringref;
1493                         switch (bc) {
1494                         case _ldc:    vbc = _aldc; break;
1495                         case _ldc_w:  vbc = _aldc_w; break;
1496                         default:      assert(false);
1497                         }
1498                         break;
1499                     case CONSTANT_Class:
1500                         bc_which = bc_classref;
1501                         switch (bc) {
1502                         case _ldc:    vbc = _cldc; break;
1503                         case _ldc_w:  vbc = _cldc_w; break;
1504                         default:      assert(false);
1505                         }
1506                         break;
1507                     default:
1508                         bc_which = null;
1509                         assert(false);
1510                     }
1511                     break;
1512                 case CONSTANT_Class:
1513                     // Use a special shorthand for the current class:
1514                     if (ref == curClass.thisClass)  ref = null;
1515                     bc_which = bc_classref; break;
1516                 case CONSTANT_Fieldref:
1517                     bc_which = bc_fieldref; break;
1518                 case CONSTANT_Methodref:
1519                     bc_which = bc_methodref; break;
1520                 case CONSTANT_InterfaceMethodref:
1521                     bc_which = bc_imethodref; break;
1522                 default:
1523                     bc_which = null;
1524                     assert(false);
1525                 }
1526                 bc_codes.putByte(vbc);
1527                 bc_which.putRef(ref);
1528                 // handle trailing junk
1529                 if (bc == _multianewarray) {
1530                     assert(i.getConstant() == code.getByte(i.getPC()+3));
1531                     // Just dump the byte into the bipush pile
1532                     bc_byte.putByte(0xFF & i.getConstant());
1533                 } else if (bc == _invokeinterface) {
1534                     assert(i.getLength() == 5);
1535                     // Make sure the discarded bytes are sane:
1536                     assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8);
1537                 } else {
1538                     // Make sure there is nothing else to write.
1539                     assert(i.getLength() == ((bc == _ldc)?2:3));
1540                 }
1541                 continue;
1542             }
1543             int slot = i.getLocalSlot();
1544             if (slot >= 0) {
1545                 bc_codes.putByte(bc);
1546                 bc_local.putInt(slot);
1547                 int con = i.getConstant();
1548                 if (bc == _iinc) {
1549                     if (!i.isWide()) {
1550                         bc_byte.putByte(0xFF & con);
1551                     } else {
1552                         bc_short.putInt(0xFFFF & con);
1553                     }
1554                 } else {
1555                     assert(con == 0);
1556                 }
1557                 continue;
1558             }
1559             // Generic instruction.  Copy the body.
1560             bc_codes.putByte(bc);
1561             int pc = i.getPC()+1;
1562             int npc = i.getNextPC();
1563             if (pc < npc) {
1564                 // Do a few remaining multi-byte instructions.
1565                 switch (bc) {
1566                 case _sipush:
1567                     bc_short.putInt(0xFFFF & i.getConstant());
1568                     break;
1569                 case _bipush:
1570                     bc_byte.putByte(0xFF & i.getConstant());
1571                     break;
1572                 case _newarray:
1573                     bc_byte.putByte(0xFF & i.getConstant());
1574                     break;
1575                 default:
1576                     assert(false);  // that's it
1577                 }
1578             }
1579         }
1580         bc_codes.putByte(_end_marker);
1581         bc_codes.elementCountForDebug++;
1582         codeHist[_end_marker]++;
1583         endCode();
1584     }
1585 
1586     int[] codeHist = new int[1<<8];
1587     int[] ldcHist  = new int[20];
1588     void printCodeHist() {
1589         assert(verbose > 0);
1590         String[] hist = new String[codeHist.length];
1591         int totalBytes = 0;
1592         for (int bc = 0; bc < codeHist.length; bc++) {
1593             totalBytes += codeHist[bc];
1594         }
1595         for (int bc = 0; bc < codeHist.length; bc++) {
1596             if (codeHist[bc] == 0) { hist[bc] = ""; continue; }
1597             String iname = Instruction.byteName(bc);
1598             String count = "" + codeHist[bc];
1599             count = "         ".substring(count.length()) + count;
1600             String pct = "" + (codeHist[bc] * 10000 / totalBytes);
1601             while (pct.length() < 4) {
1602                 pct = "0" + pct;
1603             }
1604             pct = pct.substring(0, pct.length()-2) + "." + pct.substring(pct.length()-2);
1605             hist[bc] = count + "  " + pct + "%  " + iname;
1606         }
1607         Arrays.sort(hist);
1608         System.out.println("Bytecode histogram ["+totalBytes+"]");
1609         for (int i = hist.length; --i >= 0; ) {
1610             if ("".equals(hist[i]))  continue;
1611             System.out.println(hist[i]);
1612         }
1613         for (int tag = 0; tag < ldcHist.length; tag++) {
1614             int count = ldcHist[tag];
1615             if (count == 0)  continue;
1616             System.out.println("ldc "+ConstantPool.tagName(tag)+" "+count);
1617         }
1618     }
1619 }